unit BaseRuleData;

interface

const
  cNodeDataSize     = 64;
  cArrayType_Double = 1;
  cArrayType_Int64  = 2;
  
type
  PArrayNodeHead    = ^TArrayNodeHead;
  TArrayNodeHead    = packed record
    Size            : Byte;
    Length          : Byte;
    NodeIndex       : Byte;
    Status          : Byte;          
    PrevSibling     : PArrayNodeHead;
    NextSibling     : PArrayNodeHead;
  end;
  
  PArrayDoubleNode  = ^TArrayDoubleNode;
  TArrayDoubleNode  = packed record
    Head            : TArrayNodeHead;
    Value           : array[0..cNodeDataSize - 1] of double;
  end;
                  
  PArrayInt64Node   = ^TArrayInt64Node;
  TArrayInt64Node   = packed record
    Head            : TArrayNodeHead;
    Value           : array[0..cNodeDataSize - 1] of int64;
  end;
          
  PArrayNodeAccess  = ^TArrayNodeAccess;   
  TArrayNodeAccess  = packed record
    Node            : PArrayNodeHead;
    NodeIndex       : Byte;
    ArrayIndex      : integer;
  end;
             
  PChainArray       = ^TChainArray;
  TChainArray       = packed record
    Size            : LongWord;    
    Length          : LongWord;
    NodeDataSize    : Byte;
    ArrayType       : Byte;
    DefaultAccess   : TArrayNodeAccess;   
    FirstValueNode  : PArrayNodeHead;
    LastValueNode   : PArrayNodeHead;
  end;

  PArrayDouble      = ^TArrayDouble;
  TArrayDouble      = packed record
    Length          : LongWord;
    Size            : LongWord;    
    MaxValue        : double;
    MinValue        : double;
    Value           : array of double;
  end;
                  
  PArrayInt64       = ^TArrayInt64;
  TArrayInt64       = packed record
    Length          : LongWord;
    Size            : LongWord;    
    MaxValue        : Int64;
    MinValue        : Int64;    
    Value           : array of int64;    
  end;
         
  
  function CheckOutArrayDouble(ADataLength: integer = 0): PArrayDouble;
  procedure CheckInArrayDouble(var ArrayDouble: PArrayDouble);

  function CheckOutChainArray: PChainArray;
  procedure CheckInChainArray(var AChain: PChainArray);

  function CheckOutChainArrayNode(AChainArray: PChainArray): PArrayNodeHead;
  procedure CheckInChainArrayNode(AChainArray: PChainArray; var ANode: PArrayNodeHead);

  procedure SetArrayDoubleLength(ArrayDouble: PArrayDouble; ALength: integer);
  procedure SetArrayDoubleValue(ArrayDouble: PArrayDouble; AIndex: integer; AValue: double);
  function GetArrayDoubleValue(ArrayDouble: PArrayDouble; AIndex: integer): double;
                  
//  procedure SetArrayDoubleNodeValue(ArrayDoubleNode: PArrayDoubleNode; ANodeIndex: integer; AValue: double);
//  function GetArrayDoubleNodeValue(ArrayDoubleNode: PArrayDoubleNode; ANodeIndex: integer): double;

  function CheckOutArrayInt64(ADataLength: integer = 0): PArrayInt64;
  procedure CheckInArrayInt64(var ArrayInt64: PArrayInt64);

  procedure SetArrayInt64Length(ArrayInt64: PArrayInt64; ALength: integer);
  procedure SetArrayInt64Value(ArrayInt64: PArrayInt64; AIndex: integer; AValue: Int64);
  function GetArrayInt64Value(ArrayInt64: PArrayInt64; AIndex: integer): Int64;
            
//  procedure SetArrayInt64NodeValue(ArrayInt64Node: PArrayInt64Node; ANodeIndex: integer; AValue: Int64);
//  function GetArrayInt64NodeValue(ArrayInt64Node: PArrayInt64Node; ANodeIndex: integer): Int64;

implementation

function CheckOutArrayDouble(ADataLength: integer = 0): PArrayDouble;
begin
  Result := System.New(PArrayDouble);
  FillChar(Result^, SizeOf(TArrayDouble), 0);
  if 0 < ADataLength then
  begin
    SetArrayDoubleLength(Result, ADataLength);
  end;
end;

procedure CheckInArrayDouble(var ArrayDouble: PArrayDouble);
begin
  if nil = ArrayDouble then
    exit;
  SetArrayDoubleLength(ArrayDouble, 0);   
  FreeMem(ArrayDouble);
  ArrayDouble := nil;
end;

function CheckOutChainArray: PChainArray;
begin
  Result := System.New(PChainArray);
  FillChar(Result, SizeOf(TChainArray), 0);
end;
                           
procedure CheckInChainArray(var AChain: PChainArray);
begin
  if nil = AChain then
    exit;
  while nil <> AChain.LastValueNode do
  begin
    CheckInChainArrayNode(AChain, AChain.LastValueNode);
  end;
  AChain.Length := 0;
  AChain.Size := 0;
end;

//(*//            

function CheckOutChainArrayNode(AChainArray: PChainArray): PArrayNodeHead;
var
  tmpDoubleNode: PArrayDoubleNode;
begin
  Result := nil;
  if nil = AChainArray then
    exit;
  tmpDoubleNode := System.New(PArrayDoubleNode);
  FillChar(tmpDoubleNode^, SizeOf(TArrayDoubleNode), 0);
  Result := PArrayNodeHead(tmpDoubleNode);

  if nil = AChainArray.FirstValueNode then
    AChainArray.FirstValueNode := Result;
  if nil <> AChainArray.LastValueNode then
  begin
    Result.PrevSibling := AChainArray.LastValueNode;
    AChainArray.LastValueNode.NextSibling := Result;
  end;
  AChainArray.LastValueNode := Result;
  AChainArray.Size := AChainArray.Size + Result.Size;
end;

procedure CheckInChainArrayNode(AChainArray: PChainArray; var ANode: PArrayNodeHead);
begin
end;
//*)
procedure SetArrayDoubleLength(ArrayDouble: PArrayDouble; ALength: integer);
begin
  if nil = ArrayDouble then
    exit;
  SetLength(ArrayDouble.Value, ALength);
  ArrayDouble.Size := ALength;
  ArrayDouble.Length := ALength;
end;

procedure SetChainArrayLength(AChainArray: PChainArray; ALength: LongWord);
begin
  if AChainArray.Size < ALength then
  begin
    while AChainArray.Size < ALength do
      CheckOutChainArrayNode(AChainArray);
    AChainArray.Length := ALength;
  end else
  begin
    if 0 = ALength then
    begin
    end else
    begin
    end;
  end;
end;
(*//
function GetArrayDoubleNode(ArrayDouble: PArrayDouble; AIndex: integer): PArrayDoubleNode;
var
  tmpNode: PArrayDoubleNode;    
  tmpIndex: Integer;
begin
  Result := nil;  
  tmpNode := ArrayDouble.FirstValueNode;
  tmpIndex := AIndex;
  while nil <> tmpNode do
  begin
    if tmpIndex < Length(tmpNode.Value) then
    begin
      if 0 <= tmpIndex then
      begin
        Result := tmpNode;
        Result.NodeIndex := tmpIndex;
      end;
      exit;
    end;
    tmpNode := tmpNode.NextSibling;
    tmpIndex := tmpIndex - Length(tmpNode.Value);
  end;
end;
//*)
procedure SetArrayDoubleValue(ArrayDouble: PArrayDouble; AIndex: integer; AValue: double);
//var
//  tmpNode: PArrayDoubleNode;
//  tmpIndex: Integer;
begin
  ArrayDouble.value[AIndex] := AValue;
  (*//
  tmpNode := ArrayDouble.FirstValueNode;
  tmpIndex := AIndex;
  while nil <> tmpNode do
  begin
    if tmpIndex < Length(tmpNode.Value) then
    begin
      tmpNode.Value[tmpIndex] := AValue;
    end;
    tmpNode := tmpNode.NextSibling;
    tmpIndex := tmpIndex - Length(tmpNode.Value);
  end;
  //*)
end;
(*//                 
procedure SetArrayDoubleNodeValue(ArrayDoubleNode: PArrayDoubleNode; ANodeIndex: integer; AValue: double);
begin
  ArrayDoubleNode.value[ANodeIndex] := AValue;
end;
//*)
function GetArrayDoubleValue(ArrayDouble: PArrayDouble; AIndex: integer): double;
begin
  //Result := 0;
  Result := ArrayDouble.value[AIndex];
end;
(*//               
function GetArrayDoubleNodeValue(ArrayDoubleNode: PArrayDoubleNode; ANodeIndex: integer): double;
begin
  Result := ArrayDoubleNode.value[ANodeIndex];
end;
//*)
function CheckOutArrayInt64(ADataLength: integer = 0): PArrayInt64;
begin
  Result := System.New(PArrayInt64);
  FillChar(Result^, SizeOf(TArrayInt64), 0);
  if 0 < ADataLength then
  begin
    SetArrayInt64Length(Result, ADataLength);
  end;
end;
            
procedure CheckInArrayInt64(var ArrayInt64: PArrayInt64);
begin
  if nil = ArrayInt64 then
    exit;
  SetArrayInt64Length(ArrayInt64, 0);
  FreeMem(ArrayInt64);
  ArrayInt64 := nil;
end;

procedure SetArrayInt64Length(ArrayInt64: PArrayInt64; ALength: integer);
begin
  if nil = ArrayInt64 then
    exit;

  SetLength(ArrayInt64.Value, ALength);
  ArrayInt64.Size := ALength;
  ArrayInt64.Length := ALength;
end;                                     

procedure SetArrayInt64Value(ArrayInt64: PArrayInt64; AIndex: integer; AValue: Int64);
begin
  ArrayInt64.value[AIndex] := AValue;
end;
(*//
procedure SetArrayInt64NodeValue(ArrayInt64Node: PArrayInt64Node; ANodeIndex: integer; AValue: Int64);
begin
  ArrayInt64Node.value[ANodeIndex] := AValue;
end;
//*)
function GetArrayInt64Value(ArrayInt64: PArrayInt64; AIndex: integer): Int64;
begin
  //Result := 0;
  Result := ArrayInt64.value[AIndex];
end;
(*//         
function GetArrayInt64NodeValue(ArrayInt64Node: PArrayInt64Node; ANodeIndex: integer): Int64;
begin
  Result := ArrayInt64Node.value[ANodeIndex];
end;
//*)
end.
